/**
 * Copyright &copy; 2013-2015 山东易科德软件有限公司 All rights reserved.
 */
package cn.net.ecode.modules.sys.service;

import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.net.ecode.common.config.Global;
import cn.net.ecode.common.persistence.Page;
import cn.net.ecode.common.security.Digests;
import cn.net.ecode.common.service.CrudService;
import cn.net.ecode.common.service.ServiceException;
import cn.net.ecode.common.utils.Encodes;
import cn.net.ecode.common.utils.IpUtils;
import cn.net.ecode.common.web.Servlets;
import cn.net.ecode.modules.sys.dao.UserDao;
import cn.net.ecode.modules.sys.entity.Employee;
import cn.net.ecode.modules.sys.entity.Role;
import cn.net.ecode.modules.sys.entity.User;
import cn.net.ecode.modules.sys.entity.UserDataScope;
import cn.net.ecode.modules.sys.utils.DataScopeUtils;
import cn.net.ecode.modules.sys.utils.UserUtils;

/**
 * 用户管理
 * @author jiaoanjian、ThinkGem
 * @version 2015-4-24
 */
@Service
@Transactional(readOnly = true)
public class UserService extends CrudService<UserDao, User> {

	public static final String HASH_ALGORITHM = "SHA-1";
	public static final int HASH_INTERATIONS = 1024;
	public static final int SALT_SIZE = 8;

	/**
	 * 根据登录Code获取用户
	 * @param user new User().setLoginCode();
	 * @return 取不到返回null
	 */
	public User getByLoginCode(User user){
		return dao.getByLoginCode(user);
	}
	
	/**
	 * 无分页查询用户列表
	 * @param user
	 * @return
	 */
	public List<User> findList(User user) {
		// 生成数据权限过滤条件
		DataScopeUtils.genSql(user, "dsf", "company_m,office_m", "c,d");
		List<User> list = dao.findList(user);
//		// 校验最大注册用户数
//		Map<String, String> keyInfo = AuthorizingRealm.getKeyInfo();
//		int maxRegUserNum = Integer.valueOf(keyInfo.get("maxRegUserNum"));
//		if (list.size() > maxRegUserNum) {
//			return list.subList(0, maxRegUserNum);
//		}
		return list;
	}

	/**
	 * 不过滤数据权限的，无分页查询用户列表
	 * @param user
	 * @return
	 */
	public List<User> findAllList(User user) {
		List<User> list = dao.findList(user);
		return list;
	}

	/**
	 * 查询用户列表
	 * @param page
	 * @param user
	 * @return
	 */
	public Page<User> findPage(Page<User> page, User user) {
//		// 校验最大注册用户数
//		Map<String, String> keyInfo = AuthorizingRealm.getKeyInfo();
//		int maxRegUserNum = Integer.valueOf(keyInfo.get("maxRegUserNum") == null ? "0" : keyInfo.get("maxRegUserNum"));
//		if (page.getPageSize() > maxRegUserNum) {
//			page.setPageSize(maxRegUserNum);
//		}
		// 设置分页参数
		user.setPage(page);
		// 生成数据权限过滤条件
		DataScopeUtils.genSql(user, "dsf", "company_m,office_m", "c,d");
		// 执行分页查询
		page.setList(dao.findList(user));
//		// 校验最大注册用户数
//		if (page.getCount() > maxRegUserNum) {
//			page.setCount(maxRegUserNum);
//		}
		return page;
	}
	
	/**
	 * 不过滤数据权限的，查询用户列表
	 * @param page
	 * @param user
	 * @return
	 */
	public Page<User> findAllPage(Page<User> page, User user) {
		// 设置分页参数
		user.setPage(page);
		// 执行分页查询
		page.setList(dao.findList(user));
		return page;
	}

	/**
	 * 查询用户的角色数据
	 * @param user
	 * @return
	 */
	public List<Role> findUserRoleList(User user){
		return dao.findUserRoleList(user);
	}

	/**
	 * 查询用户的控制权限数据
	 * @param user
	 * @return
	 */
	public List<UserDataScope> findUserDataScopeList(User user) {
		return dao.findUserDataScopeList(user);
	}
	
	/**
	 * 根据部门和角色查找用户
	 * @param officeCode
	 * @param roleCode
	 * @return
	 */
	public List<User> findUserByOfficeAndRole(String officeCode, String roleCode){
		User user = new User();
		user.setEmployee(new Employee());
		user.getEmployee().setOfficeCode(officeCode);
		user.setRoleCode(roleCode);
		return dao.findList(user);
	}
	
	/**
	 * 保存用户
	 * @param user
	 */
	@Transactional(readOnly = false)
	public void save(User user) {
		if (user.getIsNewRecord()){
			this.addUser(user);
		}else{
			this.editUser(user);
		}
	}

	/**
	 * 新增用户
	 * @param user
	 */
	@Transactional(readOnly = false)
	public void addUser(User user) {
		if (Global.isUseCorpModel()){
			user.setId(user.getCorpCode() + "_" + user.getLoginCode());
		}else{
			user.setId(user.getLoginCode());
		}
		if (UserUtils.get(user.getUserCode()) != null) {
			throw getValidationException("登录账号已经存在");
		}
//		Map<String, String> keyInfo = AuthorizingRealm.getKeyInfo();
//		long maxRegUserNum = Long.valueOf(keyInfo.get("maxRegUserNum") == null ? "0" : keyInfo.get("maxRegUserNum"));
//		if (dao.findAllCount(new User()) < maxRegUserNum) {
			user.preInsert();
			if (user.getUserType() == null){
				user.setUserType(User.USER_TYPE_EMPLOYEE); //默认员工
			}
			if (user.getMgrType() == null){
				user.setMgrType(User.MGR_TYPE_NOT_ADMIN); //默认非管理员
			}
			user.setUserCode(user.getLoginCode());
			user.setStatus(User.STATUS_NORMAL); // 状态正常
			user.setPassword(UserService.encryptPassword(Global.getConfig("user.initPassword")));//默认密码需从配置文件提取 
			dao.insert(user);
//		} else {
//			throw new UnauthorizedException("msg:" + Encodes.decodeBase64String("5oKo55qE5pyA5aSn5rOo5YaM55So5oi35pWw5Li6IOKAnA==") + maxRegUserNum
//					+ Encodes.decodeBase64String("4oCdIOS4qu+8jOWmgumcgOeUs+ivt+WinuWKoO+8jOivt+iBlOezu+Wuouacje+8gTxici8+IDxici8+IA==")
//					+ AuthorizingRealm.getKeyCodeMessage());
//		}
		// 保存用户授权
		saveAuthorize(user);
		// 清除用户缓存
		UserUtils.clearCache(user);
	}

	/**
	 * 编辑用户
	 * @param user
	 */
	@Transactional(readOnly = false)
	public void editUser(User user) {
		user.preUpdate();
		dao.update(user);
		// 清除用户缓存
		UserUtils.clearCache(user);
	}

	/**
	 * 用户授权
	 * @param user
	 */
	@Transactional(readOnly = false)
	public void saveAuthorize(User user) {

		// 保存用户角色关联数据
		dao.deleteUserRole(user);
		if (user.getRoleList() != null && user.getRoleList().size() > 0) {
			dao.insertUserRole(user);
		}

		// 保存用户数据权限
		dao.deleteUserDataScope(user);
		if (user.getUserDataScopeList() != null && user.getUserDataScopeList().size() > 0) {
			dao.insertUserDataScope(user);
		}
		
		// 清除用户缓存
		UserUtils.clearCache(user);

	}

	/**
	 * 更新个人信息
	 * @param user
	 */
	@Transactional(readOnly = false)
	public void updateUserInfo(User user) {
		user.preUpdate();
		dao.updateUserInfo(user);
		// 清除用户缓存
		UserUtils.clearCache(user);
	}

	/**
	 * 删除用户
	 * @param user
	 */
	@Transactional(readOnly = false)
	public void delete(User user) {
		dao.delete(user);
		// 清除用户缓存
		UserUtils.clearCache(user);
	}

	/**
	 * 更新用户密码
	 * @param id
	 * @param loginName
	 * @param newPassword
	 */
	@Transactional(readOnly = false)
	public void updatePassword(String userCode, String newPassword) {
		User user = new User(userCode);
		user.setPassword(encryptPassword(newPassword));
		dao.updatePassword(user);
		// 清除用户缓存
		user.setUserCode(userCode);
		UserUtils.clearCache(user);
	}

	/**
	 * 更新密保问题
	 * @param user
	 */
	@Transactional(readOnly = false)
	public void updateQuestion(User user) {
		user.preUpdate();
		dao.updateQuestion(user);
		// 清除用户缓存
		UserUtils.clearCache(user);
	}

	/**
	 * 更新用户登录信息（最后登录IP及日期）
	 * @param user
	 */
	@Transactional(readOnly = false)
	public void updateUserLoginInfo(User user) {
		// 保存上次登录信息
		user.setOldLoginIp(user.getLoginIp());
		user.setOldLoginDate(user.getLoginDate());
		// 更新本次登录信息
		user.setLoginIp(IpUtils.getRemoteAddr(Servlets.getRequest()));
		user.setLoginDate(new Date());
		dao.updateLoginInfo(user);
	}
	
	/**
	 * 更改引用的姓名(根据用户类型和引用代码)
	 * @param user
	 * @return
	 */
	@Transactional(readOnly = false)
	public int updateRefNameByRefCode(User user){
		user.preUpdate();
		int count = dao.updateRefNameByRefCode(user);
		// 清除用户缓存
		UserUtils.clearCache(user);
		return count;
	}

	/**
	 * 生成密文密码，生成随机的16位salt并经过1024次 sha-1 hash
	 * @param plainPassword 明文密码
	 * @return 16位salt密钥  + 40位hash密码
	 */
	public static String encryptPassword(String plainPassword) {
		byte[] salt = Digests.generateSalt(SALT_SIZE);
		byte[] hashPassword = Digests.sha1(plainPassword.getBytes(), salt, HASH_INTERATIONS);
		return Encodes.encodeHex(salt) + Encodes.encodeHex(hashPassword);

	}

	/**
	 * 生成密文密码，生成随机的16位salt并经过1024次 sha-1 hash
	 * @param plainPassword 明文密码
	 * @return 16位salt密钥  + 40位hash密码
	 * @deprecated encryptPassword(plainPassword);
	 */
	@Deprecated
	public static String entryptPassword(String plainPassword) {
		return encryptPassword(plainPassword);
	}

	/**
	 * 验证密码正确性
	 * @param plainPassword 明文密码
	 * @param password 密文密码
	 * @return 验证成功返回true
	 */
	public static boolean validatePassword(String plainPassword, String password) {
		byte[] salt = Encodes.decodeHex(password.substring(0, 16));
		byte[] hashPassword = Digests.sha1(plainPassword.getBytes(), salt, HASH_INTERATIONS);
		return password.equals(Encodes.encodeHex(salt) + Encodes.encodeHex(hashPassword));
	}

	/**
	 * 停用用户
	 * @param user
	 * @return
	 */
	@Transactional(readOnly = false)
	public int disableUser(User user) {
		user.setStatus(User.STATUS_DISABLE);
		user.preUpdate();
		int count = dao.updateUserStatus(user);
		// 清除用户缓存
		UserUtils.clearCache(user);
		return count;
	}

	/**
	 * 启用/解冻用户
	 * @param user
	 * @return
	 */
	@Transactional(readOnly = false)
	public int activateUser(User user) {
		user.setStatus(User.STATUS_NORMAL);
		user.preUpdate();
		int count = dao.updateUserStatus(user);
		// 清除用户缓存
		UserUtils.clearCache(user);
		return count;
	}

	/**
	 * 冻结用户
	 * @param user
	 * @return
	 */
	@Transactional(readOnly = false)
	public int freezeUser(User user) {
		user.setStatus(User.STATUS_FREEZE);
		user.preUpdate();
		int count = dao.updateUserStatus(user);
		// 清除用户缓存
		UserUtils.clearCache(user);
		return count;
	}
	
	/**
	 * 更改用户状态(根据用户类型和引用代码)
	 * @param user
	 * @return
	 */
	@Transactional(readOnly = false)
	public int updateUserStatusByRefCode(User user){
		user.preUpdate();
		int count = dao.updateUserStatusByRefCode(user);
		// 清除用户缓存
		UserUtils.clearCache(user);
		return count;
	}
	
	/**
	 * 重置密码
	 * @param user
	 * @return
	 */
	@Transactional(readOnly = false)
	public void resetUserPassword(User user) {
		user = super.get(user.getUserCode());
		if (user == null){
			throw new ServiceException("该用户不存在！");
		}
		updatePassword(user.getUserCode(), Global.getConfig("user.initPassword"));
	}

	/** 
	 * 按角色查询用户
	 * @author jiangwenchao
	 * @param user
	 * @return List<User>  
	 */
	public List<User> findUserByRoleCode(User user) {
		return dao.findUserByRoleCode(user);
	}

	/** 
	 * 给角色指定用户授权
	 * @author jiangwenchao
	 * @param roleCode
	 * @param userCodes
	 * @return int  
	 */
	@Transactional(readOnly = false)
	public int saveRoleAuth(String roleCode, List<String> userCodes) {
		int count = 0;
		if (StringUtils.isNotBlank(roleCode)) {
			Role role = new Role(roleCode);
			// 清除该角色下原有所有的用户缓存
			User u = new User(new Role(role.getRoleCode()));
			List<User> userList = dao.findUserByRoleCode(u);
			for (User user : userList) {
				UserUtils.clearCache(user);
			}
			// 删除原有用户角色关联数据
			dao.deleteUserRoleByRole(role);
			if (userCodes != null && userCodes.size() > 0) {
				role.setCodesList(userCodes);
				// 插入新的用户角色关联数据
				count += dao.insertUserRoleByRole(role);
				// 清理新增的用户角色缓存
				for (String userCode : userCodes){
					User user = new User(userCode);
					UserUtils.clearCache(user);
				}
			}
		}
		return count;
	}

	@Transactional(readOnly = false)
	public void updateUser(User user) {
		dao.updateUser(user);
	}

	/**
	 * 根据用户编码获取角色列表
	 * @param userCode
	 * @return
	 */
	public List<String> findRoleList(String userCode) {
		return dao.findRoleList(userCode);
	}
}
